#!/usr/bin/env zsh

# Static build wrapper
#
# Copyleft (C) 2012-2013 Denis Roio <jaromil@dyne.org>
#
# This source code is free software; you can redistribute it and/or
# modify it under the terms of the GNU Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This source code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# Please refer to the GNU Public License for more details.
#
# You should have received a copy of the GNU Public License along with
# this source code; if not, write to:
# Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# this script modifies compiler commands to include all static
# libraries that are found.


# configuration variables

typeset -a arguments libdirs deps skip
typeset -a cflags cppflags ldflags
typeset -lA libraries # map (name, static|dynamic)
typeset -h argc

# QUIET=1 source ${ZHOME}/zmake source

TOOLCHAIN=${TOOLCHAIN:=$ZHOME/toolchains/crosstool-ng/x-tools}
ZTARGET=${ZTARGET:=arm-dyne-linux-gnueabi}


case `basename $0`; in
	static-cc|cc|gcc) cc=${TOOLCHAIN}/bin/${ZTARGET}-gcc ;;
	static-c++|c++|g++) cc=${TOOLCHAIN}/bin/${ZTARGET}-g++ ;;
	static-ld|ld) cc=${TOOLCHAIN}/bin/${ZTARGET}-gcc ;; # was -ld until 0.8
	*)
	print "Error: unknown command to static wrapper: $0"
	exit 1
esac

libdirs=(${PREFIX}/lib)
libdirs+=(${TOOLCHAIN}/x-tools/arm-dyne-linux-gnueabi/sysroot/usr/lib)
cflags=(${=CFLAGS})
ldflags+=(${=LDFLAGS})

libraries+=(ld-linux-x86 skip)
libraries+=(linux-vdso   skip)
libraries+=(c            skip)
# libraries+=(rt           skip)
libraries+=(gcc		 skip)
libraries+=(gcc_s	 skip)

#	libraries+=(pthread      shared)
#	libraries+=(dl           shared)
#	libraries+=(m            shared)

##########################

arguments=($@)

linkdep() {
    # # descend lib dependencies
    dep="`basename ${1}`"
    { test "$dep" = "" } && { print "Error: linkdep called with void argument"; return 1 }

    dep=${dep/lib/} # strip lib- prefix

    # check if known
    { test "${libraries[$dep]}" = "skip" } && {
	# to be skipped
	print "$dep :: skip"
	return 3
    }

    { test "${libraries[$dep]}" = "shared" } && {
	# force shared
	arguments+=("-l${dep}")
	isshared=true
	print "$dep :: shared"
	return 1
    }

    # check if a static lib is present
    for l in ${=libdirs}; do
	static="${l}/lib${dep}.a"	
	shared="${l}/lib${dep}.so"
	{ test -r "$shared" } || { shared="${l}/lib${dep}" }

	{ ! test -r "$shared" } && { ! test -r "$static" } && { continue }

	# save deps
	{ test -r "$shared" } && {
	    for dd in `ldd $shared | awk '{print $1}'`; do
		deps+=($dd); done
	}

	if [ -r "$static" ];   then
	    print "$dep :: static :: $static <> ${arguments[$argc]}"
	    arguments[$argc]="" # remove from arguments
	    arguments+=($static);
	    libraries+=($dep static)
	    return 0

	elif [ -r "$shared" ]; then
	    print "$dep :: shared :: $shared <> ${arguments[$argc]}"
	    arguments[$argc]="" # remove from arguments
	    arguments+=($shared);
	    isshared=true
	    libraries+=($dep dynamic)

	    return 1

	else print "$dep not found in ${l}";  return 10

	fi
    done

}

# check if we are linking
action=compile # or link

echo $arguments | grep -i ' -l' > /dev/null
{ test $? = 0 } && {
    action=link
    argc=0
    for i in ${=arguments}; do
	argc=$(( $argc + 1 ))

	# is it a new library path?
	{ test "$i[1,2]" = "-L" } && {
	    lib=${i/-L/}
	    libdirs=($libdirs $lib)
	    continue
	}

	# is it a shared library link argument?
	{ test "$i[1,2]" = "-l" } && {
	    lib=${i/-l/}

	    linkdep "lib${lib}"
	}
    done
    
    echo "-= Process sub dependencies"
    # eliminate duplicates
    typeset -U deps

    for d in ${=deps}; do

	# check if it was already made static
	ds="`print ${d/lib/} | cut -d. -f1`"

	{ test "$libraries[$ds]" = "static" } && { continue }
	linkdep "lib${ds}"
    done

    # check if full static
    { test -z $isshared } && { ldflags+=(-static -static-libgcc) }
}

# remove duplicate arguments
# typeset -U arguments

# execute
case "$action" in
	compile) print "[CC] $cc ${=cflags} ${=arguments}"
		$cc ${cflags} ${arguments} ;;
	link) print "[LD] ${TOOLCHAIN}/bin/${ZTARGET}-ld ${=ldflags} ${=arguments}"
		$cc ${ldflags} ${arguments} ;;
esac
return $?



